#include "tbcore/reflection/reflection.hpp"

#include "tbcore/base/mutex.hpp"
#include "tbcore/base/logging.hpp"
#include "tbcore/base/global_initializer.hpp"
#include "tbcore/base/singleton_activator.hpp"
#include "tbcore/base/unique_id.hpp"

#include "tbcore/reflection/variant.hpp"
#include "tbcore/reflection/property.hpp"
#include "tbcore/reflection/function.hpp"
#include "tbcore/reflection/type_info.hpp"
#include "tbcore/reflection/type_node.hpp"
#include "tbcore/reflection/type_cast.hpp"
#include "tbcore/reflection/allocator.hpp"
#include "tbcore/reflection/object.hpp"
#include "tbcore/reflection/unique_object.hpp"
#include "tbcore/reflection/collection_enumer.hpp"
#include "tbcore/reflection/lua_types.hpp"

TB_NAMESPACE_BEGIN

REGISTER_BEGIN(Object)
REGISTER_END()

REGISTER_BEGIN(NObject)
REGISTER_FIELD2(Name, name_, GetName, SetName, "Name")
REGISTER_END()

REGISTER_BEGIN(UniqueObject)
REGISTER_FIELD2(ObjectId, objId_, GetObjectId, SetObjectId, "ObjectId")
REGISTER_END()

namespace reflection {

TypeInfo* MakeTypeInfo() {
  TypeInfo* typeInfo = new TypeInfo;
  typeInfo->id = typeInfo->parentId = 0;
  typeInfo->interfaceId = typeInfo->interfaceImplId = 0;
  typeInfo->extInfo = nullptr;
  typeInfo->initedInheritedProperties = false;
  typeInfo->initedInheritedFunctions = false;
  return typeInfo;
}

TypeNode* MakeTypeNode() {
  TypeNode* root = new TypeNode;
  root->count = 0;
  root->parent = root->next = root->firstChild = nullptr;
  root->typeInfo = MakeTypeInfo();
  return root;
}

ExtentInfo* MakeExtentInfo() {
  ExtentInfo* ext = new ExtentInfo();
  ext->firstType = ext->secondType = 0;
  ext->iterator = nullptr;
  return ext;
}

// all user type infomation stored here
static reflectionNodeVector __buildinTypeNodes(Variant::kBuildinTypeSize);

// all user type infomation stored here
static reflectionNodeVector __userTypeNodes;

// user type mutex
static SpinMutex __userTypeMutex;

// all pure function stored here
static FunctionsType __globalFunctions;

// pure functions mutex
static SpinRWMutex __globalFunctionsMutex;

// all binding proc
static BindingProcsType __bindingProcs;

// pure functions mutex
static SpinRWMutex __bindingProcsMutex;

// watchers
static RegisterWatchersType __watchers;

// watchers mutex
static SpinRWMutex __watchersMutex;

void RegisterBuildinType(uint32 typeId, const TCHAR* name, TCHAR* desc) {
  TypeNode* node = MakeTypeNode();

  __buildinTypeNodes.push_back(node);

  //create new reflection info
  node->typeInfo = MakeTypeInfo();
  node->typeInfo->id = typeId;
  node->typeInfo->name = name;
  node->typeInfo->description = desc;
  node->typeInfo->interfaceId = 0;
  node->typeInfo->interfaceImplId = 0;
  node->typeInfo->parentId = 0;

  TB_ASSERT(typeId == __buildinTypeNodes.size());
}

#define REGISTER_BUILDIN_TYPE(id, type, name, desc) \
  RegisterBuildinType((uint32)Variant::id, _T(#name), _T(desc))

#define BUILDIN_TYPE_TUPLES \
  BOOST_PP_TUPLE_TO_LIST( \
    15, \
    ( \
      (kBoolType,     bool), \
      (kInt8Type,     int8), \
      (kUint8Type,    uint8), \
      (kInt16Type,    int16), \
      (kUint16Type,   uint16), \
      (kInt32Type,    int32), \
      (kUint32Type,   uint32), \
      (kInt64Type,    int64), \
      (kUint64Type,   uint64), \
      (kFloatType,    float), \
      (kDoubleType,   double), \
      (kDurationType, Duration), \
      (kDatetimeType, DateTime), \
			(kStringType,		String), \
			(kObjectIdType, ObjectId) \
    ) \
  ) \
  /**/

#define REGISTER_BUILDIN_TYPE_MACRO(r, data, elem) \
  REGISTER_BUILDIN_TYPE( \
    BOOST_PP_TUPLE_ELEM(2, 0, elem), \
    BOOST_PP_TUPLE_ELEM(2, 1, elem), \
    BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, elem)), \
    BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, elem)) \
  ); \
  /**/

#define REGISTER_BUILDIN_TYPES_IMPL() \
   BOOST_PP_LIST_FOR_EACH(REGISTER_BUILDIN_TYPE_MACRO, _, BUILDIN_TYPE_TUPLES)

void ClearTypeInfo();

TB_INITIALIZER_GENERAL(BuildInTypeInitializer, TB_NO_PREREQUISITES, TB_DEFAULT_DEPENDS)
	(const InitializerContext& context) {
		REGISTER_BUILDIN_TYPES_IMPL()
		atexit(reflection::ClearTypeInfo);
		return Result();
}

#undef BUILDIN_TYPE_TUPLES
#undef REGISTER_BUILDIN_TYPE_MACRO
#undef REGISTER_BUILDIN_TYPES_IMPL

uint32 RegisterType(Allocator* allocator, const TCHAR* className, uint32 parentId, uint32 interfaceId, uint32 interfaceImplId ) {
	if (strlen_ys(className) > 0) {
		if (const TypeInfo* info = GetTypeInfo(className)) {
			RegisterParent(info->id, parentId);
			RegisterInterface(info->id, interfaceId, interfaceImplId);
			return info->id;
		}
	}

  TypeNode* newNode = MakeTypeNode();

  //thread-safe
  __userTypeMutex.Lock();
	newNode->typeInfo = MakeTypeInfo();
	__userTypeNodes.push_back(newNode);
  uint32 typeId = (uint32)(Variant::kUserType + __userTypeNodes.size());
  newNode->typeInfo->id = typeId;
	newNode->typeInfo->name = className;
	newNode->typeInfo->interfaceId = interfaceId;
	newNode->typeInfo->interfaceImplId = interfaceImplId;
	newNode->typeInfo->parentId = parentId;
	newNode->typeInfo->operators.allocator = allocator;
  __userTypeMutex.Unlock();

	RegisterParent(typeId, parentId);

  return typeId;
}

void RegisterTypeName(uint32 typeId, const TCHAR* name) {
	if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
		TypeNode* node = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
		node->typeInfo->name = name;
	}
}

void RegisterNamespace( uint32 typeId, const TCHAR* nspace ) {
  if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
    TypeNode* node = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
    node->typeInfo->nspace = nspace;

    __watchersMutex.LockShared();
    for (IRegisterWatcher *w : __watchers) {
      w->OnNamespaceRegistered(typeId, nspace);
    }
    __watchersMutex.UnlockShared();
  }
}

void RegisterParent( uint32 typeId, uint32 parentId ) {
  //register as parent's child
  if (parentId > Variant::kUserType && parentId- Variant::kUserType <= __userTypeNodes.size() &&
    typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
    TypeNode* pnode = boost::addressof(__userTypeNodes[parentId - Variant::kUserType - 1]);
    TypeNode* cnode = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
    //must be thread-safe
    SpinMutex::ScopedLock lock(__userTypeMutex);
		pnode->count.fetch_add(1);

		cnode->parent = pnode;

    if (pnode->firstChild) {
      //find the last child or nothing
      TypeNode* next = pnode->next;
      while (next && next->next) {
        next = next->next;
      }

      //append new child
      if (next) {
        next->next = cnode;
      } else {
        pnode->firstChild = cnode;
      }
    }

    __watchersMutex.LockShared();
    for (IRegisterWatcher *w : __watchers) {
      w->OnParentRegistered(typeId, parentId);
    }
    __watchersMutex.UnlockShared();
  }
}

void RegisterInterface( uint32 typeId, uint32 interfaceid, uint32 interfaceImplId ) {
  if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
      TypeNode* node = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
      node->typeInfo->interfaceId = interfaceid;
      node->typeInfo->interfaceImplId = interfaceImplId;
  }
}

void RegisterConstructor( uint32 typeId, const Function* func ) {
  if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
    TypeNode* node = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
    node->typeInfo->operators.secondCtor = func;
  }
}

void RegisterProperty( uint32 typeId, Property* property ) {
  if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
    TypeNode* node = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
    node->typeInfo->properties.push_back(property);

    __watchersMutex.LockShared();
    for (IRegisterWatcher *w : __watchers) {
      w->OnPropertyRegistered(typeId, property);
    }
    __watchersMutex.UnlockShared();
  }
}

void RegisterMethod( uint32 typeId, Function* fn ) {
  if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
    TypeNode* node = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
    node->typeInfo->functions.push_back(fn);

    __watchersMutex.LockShared();
    for (IRegisterWatcher *w : __watchers) {
      w->OnMethodRegistered(typeId, fn);
    }
    __watchersMutex.UnlockShared();
  }
}

const TypeNode* GetTypeRoot() {
  return boost::addressof(__userTypeNodes.front());
}

const TypeInfo* GetTypeInfo( uint32 typeId ) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    return node->typeInfo;
  }

  return nullptr;
}

const TCHAR* GetTypeName( uint32 typeId ) {
  if (const TypeInfo* info = GetTypeInfo(typeId)) {
    return info->name.data();
  } else {
    return _T("unknown");
  }
}

const TCHAR* GetTypeDescription( uint32 typeId ) {
  if (const TypeInfo* info = GetTypeInfo(typeId)) {
    return info->description.data();
  } else {
    return _T("unknown");
  }
}

ConstPropertiesType GetProperties(uint32 typeId) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    if (node && node->typeInfo) {
      ConstPropertiesType inheritedProperties;

      if (!node->typeInfo->initedInheritedProperties) {
        SpinRWMutex::ScopedWriteLock lock(node->typeInfo->mutex);

        for (size_t i = 0; i < node->typeInfo->properties.size(); ++i) {
          inheritedProperties.push_back(boost::addressof(node->typeInfo->properties[i]));
        }

        const TypeNode* parentNode = node->parent;
        while (parentNode) {
          if (parentNode->typeInfo) {
						for (size_t i = 0; i < parentNode->typeInfo->properties.size(); ++i) {
							inheritedProperties.push_back(boost::addressof(parentNode->typeInfo->properties[i]));
            }
          }
          parentNode = parentNode->parent;
        }
        node->typeInfo->inheritedProperties = inheritedProperties;
        node->typeInfo->initedInheritedProperties = true;
      } else {
        SpinRWMutex::ScopedReadLock lock(node->typeInfo->mutex);
        return node->typeInfo->inheritedProperties;
      }
      return inheritedProperties;
    }
  } 
  return ConstPropertiesType();
}

ConstFunctionsType GetFunctions(uint32 typeId) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    if (node && node->typeInfo) {
      ConstFunctionsType inheritedFunctions;

      if (!node->typeInfo->initedInheritedFunctions) {
        SpinRWMutex::ScopedWriteLock lock(node->typeInfo->mutex);

        for (size_t i = 0; i < node->typeInfo->functions.size(); ++i) {
          inheritedFunctions.push_back(boost::addressof(node->typeInfo->functions[i]));
        }

        const TypeNode* parentNode = node->parent;
        while (parentNode) {
          if (parentNode->typeInfo) {
            for (size_t i = 0; i < parentNode->typeInfo->functions.size(); ++i) {
              inheritedFunctions.push_back(boost::addressof(parentNode->typeInfo->functions[i]));
            }
          }
          parentNode = parentNode->parent;
        }
        node->typeInfo->inheritedFunctions = inheritedFunctions;
        node->typeInfo->initedInheritedFunctions = true;
      } else {
        SpinRWMutex::ScopedReadLock lock(node->typeInfo->mutex);
        return node->typeInfo->inheritedFunctions;
      }
      return inheritedFunctions;
    }
  }
  return ConstFunctionsType();
}

const Property* GetProperty( uint32 typeId, const TCHAR* propName ) {
  if (const TypeInfo* info = GetTypeInfo(typeId)) {
    if (info->properties.empty()) {
      return nullptr;
    }

    PropertiesType::const_iterator findIter 
      = std::find_if(info->properties.begin(), info->properties.end(), 
      [propName](const Property& info) -> bool {
        return info.propName == propName;
      }
    );

    if (findIter != info->properties.end()) {
      return boost::addressof(*findIter);
    }
  }

  return nullptr;
}

uint32 GetParent( uint32 typeId ) {
  if (const TypeInfo* info = GetTypeInfo(typeId)) {
    return info->parentId;
  } else {
    return 0;
  }
}

const TypeInfo* GetParentInfo( uint32 typeId ) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    if (node->parent) {
      return node->parent->typeInfo;
    }
  }

  LKERNEL() << "no parent";
  return nullptr;
}

void GetParents( uint32 typeId, std::vector<uint32> ids, int depth /*= -1*/ ) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    int d = 0;
    TypeNode* parent = node->parent;
    while (parent && (depth == -1 || d < depth)) {
      ids.push_back(parent->typeInfo->id);
      parent = parent->parent;
    }
  }
}

void GetParentsInfo( uint32 typeId, std::vector<TypeInfo*>& infos, int depth /*= -1*/ ) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    int currDepth = 0;
    TypeNode* parent = node->parent;

    while (parent && (depth == -1 || currDepth < depth)) {
      infos.push_back(parent->typeInfo);
      parent = parent->parent;
      currDepth++;
    }
  }
}

void GetChildren( const TypeNode* node, std::vector<uint32>& ids, int depth ) {
  if (0 == depth) {
    return;
  }

  TypeNode* firstChild = node->firstChild;

  while (firstChild) {
    ids.push_back(firstChild->typeInfo->id);

    GetChildren(firstChild, ids, depth - 1);

    firstChild = firstChild->next;
  }
}

void GetChildren( uint32 typeId, std::vector<uint32>& ids, int depth /*= 1*/ ) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    GetChildren(node, ids, depth);
  }
}

void GetChildrenInfo( const TypeNode* node, std::vector<TypeInfo*>& infos, int depth /*= 1*/ ) {
  if (0 == depth) {
    return;
  }

  TypeNode* firstChild = node->firstChild;

  while (firstChild) {
    infos.push_back(firstChild->typeInfo);

    GetChildrenInfo(firstChild, infos, depth - 1);

    firstChild = firstChild->next;
  }
}

void GetChildrenInfo( uint32 typeId, std::vector<TypeInfo*>& infos, int depth /*= 1*/ ) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    GetChildrenInfo(node, infos, depth);
  }
}

const TCHAR* GetInheritancePath( uint32 typeId ) {
	if (const TypeNode* node = GetTypeNode(typeId)) {
		if (node->typeInfo->inheritancePath.empty()) {
			std::vector<TypeInfo*> infos;
			GetParentsInfo(typeId, infos, -1);
			if (!infos.empty()) {
				node->typeInfo->inheritancePath.append(infos[0]->name);
			}

			for (size_t i = 1; i < infos.size(); ++i) {
				node->typeInfo->inheritancePath.append(_T("/")).append(infos[i]->name);
			}

			if (node->typeInfo->inheritancePath.empty()) {
				node->typeInfo->inheritancePath = _T("/");
			}
			return node->typeInfo->inheritancePath.c_str();
		}
	}

  return _T("");
}

void SetObjectPropertyValue( void* obj, Property* prop, const Variant* val, bool raw /*= false*/ ) {
  prop->Set(obj, *val, raw);
}

bool IsKindOf( uint32 typeId, uint32 parentId ){
  if (typeId == parentId) {
    return true;
  }
  if (const TypeNode* node = GetTypeNode(typeId)) {
    TypeNode* parent = node->parent;
    while (parent) {
      if (parent->typeInfo->id == parentId) {
        return true;
      }

      parent = parent->parent;
    }
  }
  return false;
}

const TypeNode* GetTypeNode( uint32 typeId ) {
	if (typeId > Variant::kNullType && typeId <= Variant::kObjectIdType) {
    return boost::addressof(__buildinTypeNodes[typeId - 1]);
  }

  if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
    return boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
  }

  return nullptr;
}

void *ConstructRaw(const TCHAR* className) {
  if (const TypeInfo* info = GetTypeInfo(className)) {
    return ConstructRaw(info);
  }
  return nullptr;
}

void *ConstructRaw(uint32 typeId) {
  if (const TypeInfo* info = GetTypeInfo(typeId)) {
    return ConstructRaw(info);
  }
  return nullptr;
}

void *ConstructRaw(const TypeInfo* typeInfo) {
  if (TB_VALID_TYPE(typeInfo->id)) {
    return typeInfo->operators.allocator->Malloc();
  }

#undef MAKE_SIMPLE_TYPE_VARIANT_IMPL 

  LWARNING() << "construct unknown type failed, type id: " << typeInfo->id;

  return nullptr;
}

Variant ConstructType(const TypeInfo* typeInfo, bool isSharedPtr) {
  if (Variant::IsUserTypeId(typeInfo->id)) {
    void *obj = ConstructRaw(typeInfo);
    if (!obj) return Variant();

    if (isSharedPtr) {
      return Variant::FromObject(typeInfo->operators.allocator->AssociatePtr(obj), typeInfo->id, typeInfo->operators.allocator);
    } else {
      return Variant::FromObject(obj, typeInfo->id, typeInfo->operators.allocator);
    }
  }
  else 
  {
#define MAKE_SIMPLE_TYPE_VARIANT_IMPL(t) \
  return Variant(VariantTrait<t>::Default())

    switch (typeInfo->id) {
    case Variant::kEnumType:
    case Variant::kInt32Type:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(int32);
    case Variant::kBoolType:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(bool);
    case Variant::kInt8Type:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(int8);
    case Variant::kUint8Type:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(uint8);
    case Variant::kInt16Type:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(int16);
    case Variant::kUint16Type:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(uint16);
    case Variant::kUint32Type:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(uint32);
    case Variant::kFloatType:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(float);
    case Variant::kDoubleType:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(double);
    case Variant::kStringType:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(String);
    case Variant::kDurationType:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(Duration);
    case Variant::kDatetimeType:
      MAKE_SIMPLE_TYPE_VARIANT_IMPL(DateTime);
    }
  }

#undef MAKE_SIMPLE_TYPE_VARIANT_IMPL 

  LWARNING() << "construct unknown type failed, type id: " << typeInfo->id;

  return Variant();
}

void DestroyType(uint32 typeId, void *data) {
  if (const TypeInfo *info = GetTypeInfo(typeId)) {
    info->operators.allocator->Free(data);
  } else {
    LERROR() << "destroy object failed, no related allocator.";
  }
}

Variant ConstructType( uint32 typeId, bool isSharedPtr ) {
  if (const TypeInfo* info = GetTypeInfo(typeId)) {
    return ConstructType(info, isSharedPtr);
  }
  return Variant();
}

Variant ConstructType(const TCHAR* className, bool isSharedPtr /*= true*/) {
  if (const TypeInfo* info = GetTypeInfo(className)) {
    return ConstructType(info, isSharedPtr);
  }
  return Variant();
}

Variant DeepCopy(const Variant* val) {
  const void* data = val->ConstData();
  Variant v = ConstructType(val->TypeId(), val->TypeFlag() == Variant::kSharedPtrTypeFlag);
  if (!v.IsNull()) {
    DeepCopy(val->ConstData(), v.Data(), val->TypeId());
  }
  return v;
}

void DeepCopy(const void* src, void* dst, uint32 typeId) {
  if (const TypeNode* node = GetTypeNode(typeId)) {
    if (const TypeInfo* info = node->typeInfo) {
      for (size_t i = 0; i < info->properties.size(); ++i) {
        const Property& property =  info->properties.at(i);
        property.Set(dst, property.Get(src));
      }
      TypeNode* parentNode = node->parent;
      while (parentNode) {
        if (const TypeInfo* parentInfo = parentNode->typeInfo) {
          for (size_t i = 0; i < parentInfo->properties.size(); ++i) {
            const Property& property =  parentInfo->properties.at(i);
            property.Set(dst, property.Get(src));
          }
        } else {
          break;
        }
        parentNode = parentNode->parent;
      }
    }
  }
}

uint32 GetTypeId(const TCHAR* className) {
  if (const TypeNode* node = GetTypeNode(className)) {
    node->typeInfo->id;
  }

  return 0;
}

const TypeNode* GetTypeNode(const TCHAR* className) {
  for (size_t i = 0; i < __buildinTypeNodes.size(); ++i) {
    const TypeNode* node = boost::addressof(__buildinTypeNodes[i]);
    if (node->typeInfo && node->typeInfo->name == className) {
      return node;
    }
  }

  for (size_t i = 0; i < __userTypeNodes.size(); ++i) {
    const TypeNode* node = boost::addressof(__userTypeNodes[i]);
    if (node->typeInfo && node->typeInfo->name == className) {
      return node;
    }
  }

  return nullptr;
}

const TypeInfo* GetTypeInfo(const TCHAR* className) {
  if (const TypeNode* node = GetTypeNode(className)) {
    return node->typeInfo;
  }

  return nullptr;
}

void ClearTypeInfo() {
  for (size_t i = 0; i < __buildinTypeNodes.size(); ++i) {
		TypeNode& node = __buildinTypeNodes[i];

    if (node.typeInfo->extInfo) {
      TB_SAFE_DELETE(node.typeInfo->extInfo->iterator);
      TB_SAFE_DELETE(node.typeInfo->extInfo);
    }

    TB_SAFE_DELETE(node.typeInfo);
  }

  for (size_t i = 0; i < __userTypeNodes.size(); ++i) {
    TypeNode& node = __userTypeNodes[i];

    if (node.typeInfo->extInfo) {
      TB_SAFE_DELETE(node.typeInfo->extInfo->iterator);
      TB_SAFE_DELETE(node.typeInfo->extInfo);
    }

    TB_SAFE_DELETE(node.typeInfo);
  }
}

void RegisterContainer( uint32 typeId, uint32 firstType, uint32 secondType, CollectionEnumer* iterator ) {
  if (typeId > Variant::kUserType && typeId - Variant::kUserType <= __userTypeNodes.size()) {
    TypeNode* node = boost::addressof(__userTypeNodes[typeId - Variant::kUserType - 1]);
    node->typeInfo->extInfo = MakeExtentInfo();
    node->typeInfo->extInfo->firstType = firstType;
    node->typeInfo->extInfo->secondType = secondType;
    node->typeInfo->extInfo->iterator = iterator;
  }
}

void RegisterGlobalFunction(const TCHAR* nspace, Function* fn) {
  SpinRWMutex::ScopedWriteLock lock(__globalFunctionsMutex);
	String fnname;
	if (strlen_ys(nspace) > 0) {
		fnname = String(nspace) + _T(".") + fn->name;
	}	else {
		fnname = fn->name;
	}

	FunctionsType::iterator it = std::find_if(
		__globalFunctions.begin(),
		__globalFunctions.end(),
		[&](Function& fn_) {
			return fn_.name == fnname;
	});
	if (it == __globalFunctions.end()) {
		fn->name = fnname;
		__globalFunctions.push_back(fn);
	}
}

ConstFunctionsType GetGlobalFunctions() {
  SpinRWMutex::ScopedReadLock lock(__globalFunctionsMutex);
  ConstFunctionsType fns;
  for (FunctionsType::iterator it = __globalFunctions.begin();
    it != __globalFunctions.end();
    ++it) {
    fns.push_back(boost::addressof(*it));
  }
  return fns;
}

void RegisterBindingProc(BindingProcType proc) {
  SpinRWMutex::ScopedWriteLock lock(__bindingProcsMutex);
  __bindingProcs.push_back(proc);
}

BindingProcsType GetBindingProcs() {
  SpinRWMutex::ScopedReadLock lock(__bindingProcsMutex);
  return __bindingProcs;
}

void RegisterBegin(uint32 typeId) {
  __watchersMutex.LockShared();
  for (IRegisterWatcher *w : __watchers) {
    w->OnRegisterBegin(typeId);
  }
  __watchersMutex.UnlockShared();
}

void RegisterEnd(uint32 typeId) {
  __watchersMutex.LockShared();
  for (IRegisterWatcher *w : __watchers) {
    w->OnRegisterEnd(typeId);
  }
  __watchersMutex.UnlockShared();
}

void AddRegisterWatcher(IRegisterWatcher *watcher) {
  __watchersMutex.LockExclusive();
  RegisterWatchersType::iterator findItor = 
    std::find(__watchers.begin(), __watchers.end(), watcher);
  if (findItor == __watchers.end()) {
    __watchers.push_back(watcher);
  } else {
    LWARNING() << "watcher is exists";
  }
  __watchersMutex.UnlockExclusive();
}

void RemoveRegisterWatcher(IRegisterWatcher *watcher) {
  __watchersMutex.LockExclusive();
  RegisterWatchersType::iterator findItor =
    std::find(__watchers.begin(), __watchers.end(), watcher);
  if (findItor != __watchers.end()) {
    __watchers.erase(findItor);
  }
  __watchersMutex.UnlockExclusive();
}

} //namespace reflection

TB_NAMESPACE_END
